package com.bobo.nutzbook.module;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.DaoException;
import org.nutz.dao.FieldFilter;
import org.nutz.dao.util.Daos;
import org.nutz.img.Images;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.Mvcs;
import org.nutz.mvc.Scope;
import org.nutz.mvc.adaptor.JsonAdaptor;
import org.nutz.mvc.annotation.AdaptBy;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Attr;
import org.nutz.mvc.annotation.By;
import org.nutz.mvc.annotation.Filters;
import org.nutz.mvc.annotation.GET;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.POST;
import org.nutz.mvc.annotation.Param;
import org.nutz.mvc.filter.CheckSession;
import org.nutz.mvc.impl.AdaptorErrorContext;
import org.nutz.mvc.upload.TempFile;
import org.nutz.mvc.upload.UploadAdaptor;

import com.bobo.nutzbook.bean.UserProfile;
import com.bobo.nutzbook.util.Toolkit;

@IocBean
@At("/user/profile")
@Ok("json")
@Filters(@By(type=CheckSession.class, args={"me", "/"})) // 检查当前Session是否带me这个属性
public class UserProfileModule extends BaseModule {

	@At("/")
    @GET
    @Ok("jsp:/jsp/user/profile")
    public UserProfile index(@Attr(scope=Scope.SESSION, value="me")int userId, HttpSession session) {
        return get(userId);
    }
	
	@At
	public UserProfile get(@Attr(scope=Scope.SESSION, value="me") int userId) {
		
		UserProfile profile = Daos.ext(dao, FieldFilter.locked(UserProfile.class, "avatar")).fetch(UserProfile.class, userId);
		if (profile == null)
		{
			profile = new UserProfile();
			profile.setUserId(userId);
			profile.setCreateTime(new Date());
			profile.setUpdateTime(new Date());
			dao.insert(profile);
		}
		return profile;
	}
	
	@At
	@Ok("void")
	@AdaptBy(type=JsonAdaptor.class)
	public void update(@Param("..") UserProfile profile, @Attr(scope=Scope.SESSION, value="me") int userId) {
		
		if (profile == null) return;
		
		profile.setUserId(userId);//防止恶意修改其他用户信息
		profile.setUpdateTime(new Date());
		profile.setAvatar(null);//不修改该字段
		//取出旧的用户信息
		UserProfile old = get(userId);
		if (old.getEmail() == null)
		{
			//老的邮箱为null,所以新的肯定是未check的状态
			profile.setEmailChecked(false);
		}
		else
		{
			if (profile.getEmail() == null)//没有设置新邮箱，就用旧邮箱覆盖
			{
				profile.setEmail(old.getEmail());
				profile.setEmailChecked(old.isEmailChecked());
			}
			else if (!profile.getEmail().equals(old.getEmail()))//设置了新的邮箱
			{
				//果断设置为未检查状态
				profile.setEmailChecked(false);
			}
		}
		
		Daos.ext(dao, FieldFilter.locked(UserProfile.class, "avatar")).update(profile);
	}
	
	@At("/avatar")
	@Ok(">>:/user/profile")
	@AdaptBy(type=UploadAdaptor.class, 
			args={"${app.root}/WEB-INF/tmp/user_avatar", "8192", "utf-8", "20000", "102400"}) //Upload适配器的几个参数: 临时文件夹路径,缓存环的大小,编码,临时文件夹的文件数,上传文件的最大大小
	@POST
	public void uploadAvatar(@Param("file") TempFile tf,
							@Attr(scope=Scope.SESSION, value="me") int userId,
							AdaptorErrorContext err)
	{
		String msg = null;
		if (err != null && err.getAdaptorErr() != null)
		{
			msg = "文件大小不符合规定";
		}
		else if (tf == null)
		{
			msg = "空文件";
		}
		else
		{
			UserProfile profile = get(userId);
			
			try {
				//1.解析图片
				BufferedImage image = Images.read(tf.getFile());
				//2.缩放
				image = Images.zoomScale(image, 128, 128, Color.WHITE);
				//3.转换成字节数组
				ByteArrayOutputStream out = new ByteArrayOutputStream();
				Images.writeJpeg(image, out, 0.8f);
				//4.保存到数据库
				profile.setAvatar(out.toByteArray());
				dao.update(profile, "^avatar$");
			} catch(DaoException e) {
                msg = "系统错误";
                e.printStackTrace();
            } catch (Throwable e) {
                msg = "图片格式错误";
                e.printStackTrace();
            }
		}
		
		if (msg != null)
		{
			Mvcs.getHttpSession().setAttribute("upload-error-msg", msg);
		}
	}
	
    @Ok("raw:jpg")
    @At("/avatar")
    @GET
    public Object readAvatar(@Attr(scope=Scope.SESSION, value="me")int userId, HttpServletRequest req) throws Exception {
        UserProfile profile = Daos.ext(dao, FieldFilter.create(UserProfile.class, "^avatar$")).fetch(UserProfile.class, userId);
        if (profile == null || profile.getAvatar() == null) {
            return new File(req.getSession().getServletContext().getRealPath("/rs/user_avatar/none.jpg"));
        }
        return profile.getAvatar();
    }
    
    @At("/active/mail")
    @POST
    public Object activeMail(@Attr(scope=Scope.SESSION, value="me") int userId, HttpServletRequest req) {
    	NutMap re = new NutMap();
    	UserProfile profile = get(userId);
    	if (Strings.isBlank(profile.getEmail()))
    	{
    		return re.setv("ok", false).setv("msg", "您还没有填写邮箱！");
    	}
    	String token = String.format("%s,%s,%s", userId, profile.getEmail(), System.currentTimeMillis());
    	token = Toolkit._3DES_encode(emailKEY, token.getBytes());
    	String url = req.getRequestURL().append("?token=").append(token).toString();
    	String html = "<div>如果无法点击,请拷贝一下链接到浏览器中打开<p/>验证链接 %s</div>";
    	html = String.format(html, url);
    	//http://localhost:8080/user/profile/active/mail?token=4632085136d40fd8e36353c9e3a2bea11e9d937b221c3723f2bcd84c394bdb4c460e73d67a009ad8
    	try {
			boolean ok = emailService.send(profile.getEmail(), "XXX 验证邮件 by Nutzbook", html);
			if (!ok)
				return re.setv("ok", false).setv("msg", "发送失败");
		} catch (Exception e) {
			log.debug("发送邮件失败", e);
			return re.setv("ok", false).setv("msg", "发送失败");
		}
    	
    	return re.setv("ok", true);
    }
    
    @At("/active/mail")
    @GET
    @Filters //覆盖类上的filter
    @Ok("raw") // 为了简单起见,这里直接显示验证结果就好了
    public String activeMailCallback(@Param("token") String token, HttpSession session)
    {
    	if (Strings.isBlank(token))
    		return "请不要直接访问这个链接!!!";
    	if (token.length() < 10)
    		return "非法token";
    	
    	try {
			token = Toolkit._3DES_decode(emailKEY, Toolkit.hexstr2bytearray(token));
			if (token == null)
				return "非法token";
			
			String[] tmp = token.split(",", 3);
			if (tmp.length != 3 || tmp[0].length() == 0 || tmp[1].length() == 0 || tmp[2].length() == 0 )
				return "非法token";
			
			long time = Long.parseLong(tmp[2]);
			if (System.currentTimeMillis() - time > 10*60*1000)//大于10分钟，链接超时
				return "该验证链接已经超时";
			
			int userId = Integer.parseInt(tmp[0]);
			Cnd cnd = Cnd.where("userId", "=", userId).and("email", "=", tmp[1]);
			int re = dao.update(UserProfile.class, Chain.make("emailChecked", true), cnd);
			if (re == 1)
				return "验证成功";
			return "验证失败，请重新验证!";
		} catch (Exception e) {
			log.debug("检查token时出错", e);
			return "非法token";
		}
    }
}
